#ifndef _TIMEUTIL_H_
#define _TIMEUTIL_H_

#ifndef _WIN32
#include <sys/time.h>
#endif
#include "Itoa.h"

class TimeUtil
{
public:
	static inline void Init() { tzset(); }
	static inline UInt32 Now() { return static_cast<UInt32>(time(nullptr)); }
	static inline UInt8 Day(UInt32 now = Now())
	{
		time_t now2 = static_cast<time_t>(now);
		struct tm * local = localtime(&now2);
		return local->tm_wday <= 0 ? 7 : static_cast<UInt8>(local->tm_wday);
	}
	static inline UInt32 SharpDay(int c = 0, UInt32 cur = Now())
	{
		UInt32 tmptm = (cur + timezone) / 86400 * 86400 + timezone;
		if (tmptm > cur)
			tmptm -= 86400;
		else if (tmptm + 86400 <= cur)
			tmptm += 86400;
		return tmptm + c * 86400;
	}
	static inline UInt32 SharpHour(int c, UInt32 tm = Now())
	{
		return (tm + c * 3600) / 3600 * 3600;
	}
	static inline UInt32 SharpFourtyMin(int c, UInt32 tm = Now())
	{
		return (tm + c * 2400) / 2400 * 2400;
	}
	static inline UInt32 SharpMinute(int c, UInt32 tm = Now())
	{
		return (tm + c * 60) / 60 * 60;
	}
	static std::string GetFormatTime(UInt32 tm = Now())
	{
		//2016-10-03
		std::string tmStr;
		time_t tm2 = static_cast<time_t>(tm);
		struct tm * local = localtime(&tm2);
		tmStr.append(Itoa<int>(local->tm_year + 1900));
		tmStr.append("-");
		tmStr.append(Itoa<int>(local->tm_mon + 1));
		tmStr.append("-");
		tmStr.append(Itoa<int>(local->tm_mday));
		return tmStr;
	}
	static inline UInt64 GetTick()
	{
#ifdef _WIN32
		FILETIME ft;
		GetSystemTimeAsFileTime(&ft);
		ULARGE_INTEGER epoch; // UNIX epoch (1970-01-01 00:00:00) expressed in Windows NT FILETIME
		epoch.LowPart = 0xD53E8000;
		epoch.HighPart = 0x019DB1DE;

		ULARGE_INTEGER ts;
		ts.LowPart = ft.dwLowDateTime;
		ts.HighPart = ft.dwHighDateTime;
		ts.QuadPart -= epoch.QuadPart;
		return ts.QuadPart / 10;
#else
		struct timeval tv;
		if (gettimeofday(&tv, nullptr))
			return 0;
		return tv.tv_sec * 1000000 + tv.tv_usec;
#endif
	}
	static inline UInt32 MakeTime(int year, int month, int day, int hour, int min, int sec = 0)
	{
		struct tm t;
		t.tm_year = year - 1900;
		t.tm_mon = month - 1;
		t.tm_mday = day;
		t.tm_hour = hour;
		t.tm_min = min;
		t.tm_sec = sec;
		return static_cast<UInt32>(mktime(&t));
	}
	static const UInt32 DaySec = 24 * 60 * 60;
};

#endif // _TIMEUTIL_H_
